﻿using Asp.Versioning;
using DoNet.Common.Enums;
using DoNet.Common.Extensions;
using DoNet.Common.Helpers;
using DoNet.Extensions.Filters;
using DoNet.Extensions.Middlewares;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Filters;
using System.Runtime.InteropServices;

namespace DoNet.Extensions.Setups
{
    /// <summary>
    /// Swagger 启动服务
    /// </summary>
    public static class SwaggerSetup
    {
        //private static readonly ILog log = LogManager.GetLogger(typeof(SwaggerSetup));
        /// <summary>
        /// 
        /// </summary>
        /// <param name="services"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public static void AddSwaggerSetup(this IServiceCollection services, IConfiguration config)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            // Api多版本版本配置  
            services.AddApiVersioning(o =>
            {
                o.ReportApiVersions = true;//是否在请求头中返回受支持的版本信息。
                o.AssumeDefaultVersionWhenUnspecified = true;//请求没有指明版本的情况下是否使用默认的版本。
                o.DefaultApiVersion = new ApiVersion(1, 0);//默认的版本号。
                o.ApiVersionReader = ApiVersionReader.Combine(new HeaderApiVersionReader("api-version"));////版本信息放到header ,不写在不配置路由的情况下，版本信息放到response url 中
            });

            services.AddSwaggerGen(options =>
            {
                string contactName = config.app("SwaggerDoc:ContactName").ObjectToString();
                string contactNameEmail = config.app("SwaggerDoc:ContactEmail").ObjectToString();
                string contactUrl = config.app("SwaggerDoc:ContactUrl").ObjectToString();
                string termsOfService = config.app("SwaggerDoc:TermsOfService").ObjectToString();

                //遍历出全部的版本，做文档信息展示
                typeof(SwaggerVersions).GetEnumNames().ToList().ForEach(version =>
                {
                    options.SwaggerDoc(version,
                         new OpenApiInfo()
                         {
                             Title = $"{config.app("SwaggerDoc:Title").ObjectToString()}-{RuntimeInformation.FrameworkDescription}",
                             Version = $"{version}",
                             TermsOfService = new Uri(termsOfService),
                             Description = config.app("SwaggerDoc:Description").ObjectToString(),
                             Contact = new OpenApiContact { Name = contactName, Email = contactNameEmail, Url = new Uri(contactUrl) },
                             License = new OpenApiLicense { Name = "Apache 2.0", Url = new Uri("https://www.apache.org/licenses/LICENSE-2.0") }
                         }
                    );
                });
                //options.IgnoreObsoleteActions();//忽略掉废弃接接口，即不展示
                //options.IgnoreObsoleteProperties();//废弃接接口
                options.UseInlineDefinitionsForEnums();
                try
                {
                    Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.xml").ToList().ForEach(file =>
                    {
                        options.IncludeXmlComments(file, true);
                    });
                }
                catch (Exception ex)
                {
                    //Log4NetHelper.Error("请检查并拷贝。\n" + ex.Message);
                }
                //给api添加token令牌证书
                options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}（注意两者之间是一个空格）\"",
                    Name = "Authorization",//jwt默认的参数名称
                    In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
                    Type = SecuritySchemeType.ApiKey,
                    BearerFormat = "JWT",
                    Scheme = "Bearer"
                });

                //添加安全请求
                options.AddSecurityRequirement(
                    new OpenApiSecurityRequirement {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference=new OpenApiReference{
                                Type=ReferenceType.SecurityScheme,
                                Id= "Bearer"
                            }
                        }
                        ,new string[] { }
                    }
                    }
                 );

                options.DocumentFilter<CustomDocumentFilter>();
                options.OrderActionsBy((apidesc) => apidesc.RelativePath);
                options.OperationFilter<AddRequiredHeaderParameter>();
                //开启加权锁
                options.OperationFilter<AddResponseHeadersFilter>();
                options.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
                // 在header中添加token，传递到后台
                options.OperationFilter<SecurityRequirementsOperationFilter>();
                //options.OrderActionsBy((apiDesc) => $"{apiDesc.ActionDescriptor.RouteValues["controller"]}");
                //options.g(apiDesc=> {
                //    System.Diagnostics.Debug.WriteLine(apiDesc.ID);
                //    var attribute = apiDesc.GetControllerAndActionAttributes<SwaggerControllerViewAttribute>();
                //    if (attribute.Any())
                //        return attribute.First().ControllerName + " " + attribute.First().Version;
                //    else
                //        return apiDesc.ActionDescriptor.ControllerDescriptor.ControllerName;
                //});
            });

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="app"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public static void UserSwaggerSetup(this IApplicationBuilder app, IConfiguration config)
        {
            if (app == null) throw new ArgumentNullException(nameof(app));
            app.UseMiddleware<SwaggerBasicAuthMiddleware>();
            app.UseSwagger();
            app.UseSwaggerUI(options =>
            {
                options.DocumentTitle = config.app("SwaggerDoc:Title").ObjectToString();
                typeof(SwaggerVersions).GetEnumNames().OrderBy(e => e).ToList().ForEach(version =>
                {
                    options.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{config.app("SwaggerDoc:Title").ObjectToString() + version.ToUpperInvariant()}");
                    options.RoutePrefix = string.Empty;//这里主要是不需要再输入swagger这个默认前缀
                });
                options.HeadContent = "<script async id=\"mini-profiler\" src=\"/mini-profiler-resources/includes.min.js?v=4.2.22+b27bea37e9\" data-version=\"4.2.22+b27bea37e9\" data-path=\"/mini-profiler-resources/\" data-current-id=\"144b1192-acd3-4fe2-bbc5-6f1e1c6d53df\" data-ids=\"87a1341b-995d-4d1d-aaba-8f2bfcfc9ca9,144b1192-acd3-4fe2-bbc5-6f1e1c6d53df\" data-position=\"Left\" data-scheme=\"Light\" data-authorized=\"true\" data-max-traces=\"15\" data-toggle-shortcut=\"Alt+P\" data-trivial-milliseconds=\"2.0\" data-ignored-duplicate-execute-types=\"Open,OpenAsync,Close,CloseAsync\"></script>";
            });
        }
    }
}
